﻿using System;
using System.Linq;
using System.ServiceModel.DomainServices.EntityFramework;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server.ApplicationServices;
using System.Web.Security;
using Falafel.Services.Web.Models;
using System.Web.Profile;

namespace Falafel.Services.Web
{
    [EnableClientAccess]
    public class AuthenticationService : LinqToEntitiesDomainService<FalafelEntities>, IAuthentication<User>
    {
        private static readonly User DefaultUser = new User
        {
            Name = string.Empty,
            ID = -1
        };

        public User Login(string userName, string password, bool isPersistent, string customData)
        {
            if (ValidateUser(userName, password))
            {
                FormsAuthentication.SetAuthCookie(userName, isPersistent);
                return GetUser(userName);
            }

            return null;
        }

        private bool ValidateUser(string username, string password)
        {
            // delegate validation to current membership provider (or use your own logic here! either
            // another Membership provider (Active Directory), a custom provider, or just completely
            // proprietary logic
            if (!Membership.ValidateUser(username, password))
            {
                return false;
            }
            // At this point the user has been verified.
            FalafelUser user = ObjectContext.FalafelUsers.FirstOrDefault(u => u.Login.UserName == username);

            // If the user is null then we need to create the user in the intermediary table before continuing
            // This scenario more than likely happened if someone setup the user in the "ASP.NET Web Site Administration Tool"
            // vs. this program's login registration form
            if (user == null)
            {
                MembershipUser membershipUser = Membership.GetUser(username);
                UserRegistrationService.CreateUserFromMembershipUser(membershipUser);

                return true;
            }

            // Verify verify that the user is Active
            return user.IsActive;
        }

        public User Logout()
        {
            FormsAuthentication.SignOut();
            return DefaultUser;
        }

        public User GetUser()
        {
            if ((ServiceContext != null) &&
                (ServiceContext.User != null) &&
                ServiceContext.User.Identity.IsAuthenticated)
            {
                return GetUser(ServiceContext.User.Identity.Name);
            }
            return DefaultUser;
        }

        private User GetUser(string userName)
        {
            FalafelUser user = ObjectContext.FalafelUsers.Include("Login").First(u => u.Login.UserName == userName);
            ProfileBase profile = ProfileBase.Create(userName, true);
            string friendlyName = (string) profile.GetPropertyValue("FriendlyName");

            return new User
                       {
                           Name = user.Login.UserName,
                           ID = user.ID,
                           FriendlyName = string.IsNullOrWhiteSpace(friendlyName) ? user.DisplayName : friendlyName
                       };
        }

        public void UpdateUser(User user)
        {
            // Ensure the user data that will be modified represents the currently
            // authenticated identity 
            if ((ServiceContext.User == null) ||
                (ServiceContext.User.Identity == null) ||
                !string.Equals(ServiceContext.User.Identity.Name, user.Name, StringComparison.Ordinal))
            {
                throw new UnauthorizedAccessException("You are only authorized to modify your own profile.");
            }

            throw new NotImplementedException();
        }

    }
}
